﻿using ICSharpCode.TextEditor.Document;
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System.Windows.Forms;
using Newtonsoft.Json;
using System.Diagnostics;
using System.IO;
using System.Drawing;

namespace Json
{
    public partial class Json解析窗口 : Form
    {
        private FindForm findWindow = null;

        private string MyPath = null;

        private string JsonPath = null;

        private bool isChange = true;

        public Json解析窗口(string path_1, string path_2)
        {
            InitializeComponent();
            StartPosition = FormStartPosition.CenterScreen;
            MyPath = path_2;
            JsonPath = path_1;
        }

        private void Json解析窗口_Shown(object sender, EventArgs e)
        {
            FileVersionInfo myFileVersion = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
            Text = Text + " V" + myFileVersion.FileVersion;

            try
            {
                FileSyntaxModeProvider fsmp = new FileSyntaxModeProvider(MyPath + @"\Res");
                HighlightingManager.Manager.AddSyntaxModeFileProvider(fsmp);
                Json代码编辑框.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy("Json");
                Json代码编辑框.ActiveTextAreaControl.TextArea.MouseUp += new MouseEventHandler(代码编辑框右键菜单);
                Json代码编辑框.Document.FoldingManager.FoldingStrategy = new MingFolding();
                Json代码编辑框.Font = new Font("Courier New", 11f, FontStyle.Regular);

                if (JsonPath != null)
                {
                    Json代码编辑框.LoadFile(JsonPath);

                    try
                    {
                        JObject jsondata = JObject.Parse(Json代码编辑框.Text);
                        Json代码编辑框.Text = jsondata.ToString();
                    }
                    catch {; }

                    isChange = true;
                    Text = Text.Replace("*", "");
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("初始化加载失败：" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            
        }

        private void Json代码编辑框_TextChanged(object sender, EventArgs e)
        {
            isChange = false;
            if(!Text.Contains("*")) Text = Text + "*";
            Json代码编辑框.Document.FoldingManager.UpdateFoldings(null, null);
        }

        private void 解析按钮_Click(object sender, EventArgs e)
        {
            string Data = Json代码编辑框.Text;

            if(Data != null && Data.Length > 1)
            {
                try
                {
                    JObject jsondata = JObject.Parse(Data);
                    Json代码编辑框.Text = jsondata.ToString();
                }
                catch(JsonReaderException ex)
                {
                    int index = ex.LinePosition;
                    
                    string[] key = ex.Path.Split('.');

                    string keystr = key[key.Length - 1];

                    int offset = Json代码编辑框.Text.LastIndexOf("\"" + keystr + "\"", index, StringComparison.CurrentCulture);

                    if (offset >= 0)
                    {
                        var start = Json代码编辑框.Document.OffsetToPosition(offset);
                        var end = Json代码编辑框.Document.OffsetToPosition(offset + keystr.Length + 2);
                        Json代码编辑框.ActiveTextAreaControl.SelectionManager.SetSelection(new DefaultSelection(Json代码编辑框.Document, start, end));

                        Json代码编辑框.ActiveTextAreaControl.Caret.Position = Json代码编辑框.Document.OffsetToPosition(offset);
                        Json代码编辑框.ActiveTextAreaControl.TextArea.ScrollToCaret();
                    }

                    MessageBox.Show("解析异常：" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void 清除按钮_Click(object sender, EventArgs e)
        {
            Json代码编辑框.Text = "";
        }

        private void 代码编辑框右键菜单(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                代码框右键菜单.Show(MousePosition.X, MousePosition.Y);

                菜单启用检测();
            }
        }

        private void 编辑菜单_Click(object sender, EventArgs e)
        {
            菜单启用检测();
        }

        private void 查找替换编辑_Click(object sender, EventArgs e)
        {
            if (findWindow != null)
            {
                findWindow.Close();
            }
            findWindow = new FindForm(Json代码编辑框, Left + (Width / 2), Top + (Height / 2));
            findWindow.Show();
            findWindow.TopMost = true;
        }

        private void 复制_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(Json代码编辑框.ActiveTextAreaControl.TextArea.SelectionManager.SelectedText);
        }

        private void 粘贴_Click(object sender, EventArgs e)
        {
            IDataObject data = Clipboard.GetDataObject();
            int offset = Json代码编辑框.ActiveTextAreaControl.TextArea.Caret.Offset;
            int selectlong = Json代码编辑框.ActiveTextAreaControl.SelectionManager.SelectedText.Length;
            int startindex = Json代码编辑框.ActiveTextAreaControl.TextArea.Caret.Offset - Json代码编辑框.ActiveTextAreaControl.SelectionManager.SelectedText.Length;

            if (data.GetDataPresent(DataFormats.Text))
            {
                string test = (string)data.GetData(DataFormats.Text);
                if (test.Length > 0 && Json代码编辑框.ActiveTextAreaControl.TextArea != null)
                {
                    if(selectlong < 1)
                    {
                        Json代码编辑框.Document.Insert(offset, test);
                    }
                    else
                    {
                        Json代码编辑框.ActiveTextAreaControl.TextArea.Document.Remove(startindex, selectlong);
                        Json代码编辑框.Document.Insert(startindex, test);
                    }
                    Json代码编辑框.ActiveTextAreaControl.SelectionManager.ClearSelection();
                }
            }
        }

        private void 全选_Click(object sender, EventArgs e)
        {
            Json代码编辑框.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(new DefaultSelection(Json代码编辑框.Document, Json代码编辑框.Document.OffsetToPosition(0), Json代码编辑框.Document.OffsetToPosition(Json代码编辑框.ActiveTextAreaControl.TextArea.MotherTextEditorControl.Text.Length)));
            Json代码编辑框.ActiveTextAreaControl.TextArea.Caret.Position = Json代码编辑框.Document.OffsetToPosition(Json代码编辑框.ActiveTextAreaControl.TextArea.MotherTextEditorControl.Text.Length);
        }

        private void 退出文件_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void 打开文件_Click(object sender, EventArgs e)
        {
            if (!文件保存检测()) return;

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Json文件|*.json|文本文件|*.txt|所有文件|*.*";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                JsonPath = openFileDialog.FileName;

                Json代码编辑框.LoadFile(JsonPath);

                try
                {
                    JObject jsondata = JObject.Parse(Json代码编辑框.Text);
                    Json代码编辑框.Text = jsondata.ToString();
                }
                catch {; }

                isChange = true;
                Text = Text.Replace("*", "");
            }
        }

        private void 保存文件_Click(object sender, EventArgs e)
        {
            if(JsonPath != null)
            {
                FileStream fs = new FileStream(JsonPath, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs);
                //开始写入
                sw.Write(Json代码编辑框.Text);
                //清空缓冲区
                sw.Flush();
                //关闭流
                sw.Close();
                fs.Close();

                isChange = true;
                Text = Text.Replace("*", "");
            }
            else
            {
                另存为文件_Click(sender, e);
            }
        }

        private void 另存为文件_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Json文件|*.json|文本文件|*.txt";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                string path = saveFileDialog.FileName;

                FileStream fs = new FileStream(path, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs);
                //开始写入
                sw.Write(Json代码编辑框.Text);
                //清空缓冲区
                sw.Flush();
                //关闭流
                sw.Close();
                fs.Close();

                JsonPath = path;

                isChange = true;
                Text = Text.Replace("*", "");
            }
        }

        private void Json解析窗口_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!文件保存检测())
            {
                e.Cancel = true;
            }
        }

        private void 压缩按钮_Click(object sender, EventArgs e)
        {
            string Data = Json代码编辑框.Text;

            if (Data != null && Data.Length > 1)
            {
                try
                {
                    JObject jsondata = JObject.Parse(Data);
                    var obj = JsonConvert.DeserializeObject(Data);
                    if (obj == null)
                        return;
                    Json代码编辑框.Text = JsonConvert.SerializeObject(obj);
                    Json代码编辑框.Update();
                }
                catch (JsonReaderException ex)
                {
                    int index = ex.LinePosition;

                    string[] key = ex.Path.Split('.');

                    string keystr = key[key.Length - 1];

                    int offset = Json代码编辑框.Text.LastIndexOf("\"" + keystr + "\"", index, StringComparison.CurrentCulture);

                    if (offset >= 0)
                    {
                        var start = Json代码编辑框.Document.OffsetToPosition(offset);
                        var end = Json代码编辑框.Document.OffsetToPosition(offset + keystr.Length + 2);
                        Json代码编辑框.ActiveTextAreaControl.SelectionManager.SetSelection(new DefaultSelection(Json代码编辑框.Document, start, end));

                        Json代码编辑框.ActiveTextAreaControl.Caret.Position = Json代码编辑框.Document.OffsetToPosition(offset);
                        Json代码编辑框.ActiveTextAreaControl.TextArea.ScrollToCaret();
                    }

                    MessageBox.Show("解析异常：" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void 撤销_Click(object sender, EventArgs e)
        {
            Json代码编辑框.Undo();
        }

        private void 重做_Click(object sender, EventArgs e)
        {
            Json代码编辑框.Redo();
        }

        private void 菜单启用检测()
        {
            if (Json代码编辑框.ActiveTextAreaControl.TextArea.SelectionManager.SelectedText.Length < 1)
            {
                复制右键.Enabled = false;
                复制编辑.Enabled = false;
            }
            else
            {
                复制右键.Enabled = true;
                复制编辑.Enabled = true;
            }

            if (Json代码编辑框.Text.Length < 1)
            {
                全选右键.Enabled = false;
                全选编辑.Enabled = false;
            }
            else
            {
                全选右键.Enabled = true;
                全选编辑.Enabled = true;
            }

            IDataObject data = Clipboard.GetDataObject();

            if (data.GetDataPresent(DataFormats.Text))
            {
                string test = (string)data.GetData(DataFormats.Text);
                if (test.Length < 1)
                {
                    粘贴右键.Enabled = false;
                    粘贴编辑.Enabled = false;
                }
                else
                {
                    粘贴右键.Enabled = true;
                    粘贴编辑.Enabled = true;
                }
            }

            if (Json代码编辑框.Document.UndoStack.UndoItemCount < 0)
            {
                撤销右键.Enabled = false;
                撤销编辑.Enabled = false;
            }
            else
            {
                撤销右键.Enabled = true;
                撤销编辑.Enabled = true;
            }

            if (Json代码编辑框.Document.UndoStack.RedoItemCount < 0)
            {
                重做右键.Enabled = false;
                重做编辑.Enabled = false;
            }
            else
            {
                重做右键.Enabled = true;
                重做编辑.Enabled = true;
            }
        }

        private bool 文件保存检测()
        {
            if (Json代码编辑框.Text.Length > 0)
            {
                if (!isChange)
                {
                    DialogResult ar = MessageBox.Show("内容有改动，是否需要保存当前文档？", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);

                    switch (ar)
                    {
                        case DialogResult.Cancel:
                            return false;
                        case DialogResult.No:
                            return true;
                        case DialogResult.Yes:
                            保存文件_Click(null, null);
                            break;
                        default: return false;
                    }
                }
            }

            return true;
        }

        private void Gitee帮助_Click(object sender, EventArgs e)
        {
            Process.Start("https://gitee.com/mimocvb/PC_Json_Parse");
        }

        private void 关于帮助_Click(object sender, EventArgs e)
        {
            About ab = new About();
            ab.ShowDialog();
        }
    }

    /// <summary>
    /// 实现自定义代码折叠接口
    /// </summary>
    public class MingFolding : IFoldingStrategy
    {
        /// <summary>
        /// 代码键入或者更新时进入折叠检测
        /// </summary>
        /// <param name="document">DOM编辑框</param>
        /// <param name="fileName">文件名</param>
        /// <param name="parseInformation">信息对象</param>
        /// <returns></returns>
        public List<FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInformation)
        {
            List<FoldMarker> list = new List<FoldMarker>();

            //先进先出
            var startLines = new Stack<int>();

            for (int i = 0; i < document.TotalNumberOfLines; i++)
            {
                string text = document.GetText(document.GetLineSegment(i));

                if (text.Contains("{}") || text.Contains("[]")) continue;

                //Json大括号折叠
                if (text.Contains("{"))
                {
                    startLines.Push(i);
                }
                if (text.Contains("}"))
                {
                    if (startLines.Count > 0)
                    {
                        int start = startLines.Pop();
                        list.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length, i, 57, FoldType.TypeBody, "...}"));
                    }
                }

                //Json中括号折叠
                if (text.Contains("["))
                {
                    startLines.Push(i);
                }
                if (text.Contains("]"))
                {
                    if (startLines.Count > 0)
                    {
                        int start = startLines.Pop();
                        list.Add(new FoldMarker(document, start, document.GetLineSegment(start).Length, i, 57, FoldType.TypeBody, "...]"));
                    }
                }
            }

            return list;
        }
    }
}
